/** @file    EncodersXmlQt_Building.cpp
 *  @author  Alessandro Polo
 *  @version $Id: EncodersXmlQt_Building.cpp 2815 2010-07-31 01:11:15Z alex $
 *  @brief
 * The header for this class can be found in EncodersXmlQt_Building.h, check that file
 * for class description.
 ****************************************************************************/
/* Copyright (c) 2007-2010, WOSH - Wide Open Smart Home 
 * by Alessandro Polo - OpenSmartHome.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the OpenSmartHome.com WOSH nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Alessandro Polo ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Alessandro Polo BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ****************************************************************************/
 
 #include <framework/persistence/qt/EncodersXmlQt_Building.h>
 
 #include <framework/persistence/qt/EncodersXmlQt_Core.h>
 #include <core/ObjectAllocator.h>


namespace wosh {
 namespace persistence {
  namespace qt {

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

 WOSH_ENCODER_XML_Qt_BIND(wosh::persistence::qt::EncoderXml_Qt_Building_BuildingObject, "wosh::building::BuildingObject", 0.0, _static_EncoderXml_Qt_Building_BuildingObject )

WRESULT EncoderXml_Qt_Building_BuildingObject::serializeTo( const wosh::building::BuildingObject* object, QDomDocument& doc, QDomElement& contNode, int encoder_options ) {
	if ( object == NULL ) return WRET_ERR_PARAM;
	WRESULT ret = EncoderXml_Qt_Object::serializeTo(object, doc, contNode, encoder_options );
	EncoderBaseXmlQt::serializeString( "parent", object->getParentName(), doc, contNode, encoder_options );
//	EncoderBaseXmlQt::serializeBool( "always-raise-events", object->isAlwaysRaisingEvents(), doc, contNode, encoder_options );

	if ( object->countChildren() != 0 ) {
		QDomElement childrenNode = doc.createElement("children"); contNode.appendChild(childrenNode);
		std::vector<std::string> keys; object->getChildren(keys);
		std::vector<std::string>::const_iterator it;
		for ( it=keys.begin(); it!=keys.end(); ++it ) {
			QDomElement childNode = doc.createElement("wosh::Object");
			childNode.setAttribute("uri", QString((*it).c_str()) );
			childrenNode.appendChild(childNode);
		 }
	 }
	QDomElement node_permission = doc.createElement("permission"); contNode.appendChild(node_permission);
	ret += EncoderXml_Qt_Permission::serializeTo(&object->getPermission(), doc, node_permission, encoder_options );

	if ( isCompact(encoder_options) || !object->getGeometry().isZero() ) {
		QDomElement node_geometry = doc.createElement("geometry"); contNode.appendChild(node_geometry);
		ret += EncoderXml_Qt_Building_BuildingGeometry::serializeTo(&object->getGeometry(), doc, node_geometry, encoder_options );
	 }
	if ( isCompact(encoder_options) || !object->getProperties().isEmpty() ) {
		QDomElement node_properties = doc.createElement("properties"); contNode.appendChild(node_properties);
		ret += EncoderXml_Qt_PropertiesProvider::serializeTo(&object->getProperties(), doc, node_properties, encoder_options );
	 }
	return ret;
 }

WRESULT EncoderXml_Qt_Building_BuildingObject::deserializeFrom( wosh::building::BuildingObject* object, const QDomElement& contNode ) {
	if ( object == NULL ) return WRET_ERR_PARAM;
	WRESULT ret = EncoderXml_Qt_Object::deserializeFrom(object, contNode );

	std::string tagname;
	std::string objUri;
	std::string interfaces;
	QDomElement childrenNode = contNode.namedItem("children").toElement();
	if ( !childrenNode.isNull() ) {
		QDomNodeList nodesList = childrenNode.childNodes();
		for( unsigned int j=0; j<nodesList.length(); ++j ) {
			QDomElement childNode = nodesList.item(j).toElement();
			tagname = std::string( childNode.tagName().toLatin1().data() );
			objUri= std::string( childNode.attribute("uri").toLatin1().data() );
			if ( objUri.size() < 3 ) {
				continue;
			 }
			interfaces = std::string( childNode.attribute("interfaces").toLatin1().data() );
			InterfacesProvider* ip = new InterfacesProvider();
			ip->fromString(interfaces);
			if ( interfaces.empty() )
				ip->add(tagname);
			object->setChild( objUri, ip );
		 }
	 }
	QDomElement node_permission = contNode.namedItem("permission").toElement();
	if ( !node_permission.isNull() )
		ret += EncoderXml_Qt_Permission::deserializeFrom( (wosh::Permission*)&object->getPermission(), node_permission );
	QDomElement node_geometry = contNode.namedItem("geometry").toElement();
	if ( !node_geometry.isNull() )
		ret += EncoderXml_Qt_Building_BuildingGeometry::deserializeFrom( (wosh::building::BuildingGeometry*)&object->getGeometry(), node_geometry );
	QDomElement node_properties = contNode.namedItem("properties").toElement();
	if ( !node_properties.isNull() )
		ret += EncoderXml_Qt_PropertiesProvider::deserializeFrom(&object->getProperties(), node_properties );
	return ret;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

 WOSH_ENCODER_XML_Qt_BIND(wosh::persistence::qt::EncoderXml_Qt_Building_BuildingGeometry, "wosh::building::BuildingGeometry", 0.0, _static_EncoderXml_Qt_Building_BuildingGeometry )

void serializePoint3D( const wosh::building::Point3D& pos, QDomDocument& doc, QDomElement& posNode, int encoder_options  ) {
	EncoderBaseXmlQt::serializeDouble( "x", pos.x, doc, posNode, encoder_options );
	EncoderBaseXmlQt::serializeDouble( "y", pos.y, doc, posNode, encoder_options );
	EncoderBaseXmlQt::serializeDouble( "z", pos.z, doc, posNode, encoder_options );
 }

void deserializePoint3D( wosh::building::Point3D& pos, QDomElement& posNode ) {
	pos.x = EncoderBaseXmlQt::deserializeDouble( "x", 0, posNode );
	pos.y = EncoderBaseXmlQt::deserializeDouble( "y", 0, posNode );
	pos.z = EncoderBaseXmlQt::deserializeDouble( "z", 0, posNode );
 }

WRESULT EncoderXml_Qt_Building_BuildingGeometry::serializeTo( const wosh::building::BuildingGeometry* object, QDomDocument& doc, QDomElement& contNode, int encoder_options ) {
	if ( object == NULL ) return WRET_ERR_PARAM;
	QDomElement posNode = doc.createElement("position"); contNode.appendChild(posNode);
	serializePoint3D(object->getPosition(), doc, posNode, encoder_options);
	QDomElement bbNode = doc.createElement("bounding-box"); contNode.appendChild(bbNode);
	serializePoint3D(object->getBoundingBox(), doc, bbNode, encoder_options);
	return WRET_OK;
 }

WRESULT EncoderXml_Qt_Building_BuildingGeometry::deserializeFrom( wosh::building::BuildingGeometry* object, const QDomElement& contNode ) {
	if ( object == NULL ) return WRET_ERR_PARAM;
	WRESULT ret = WRET_OK;
	QDomElement posNode = contNode.namedItem("position").toElement();
	if ( !posNode.isNull() ) {
		wosh::building::Point3D pos = object->getPosition();
		deserializePoint3D(pos, posNode);
		object->setPosition(pos);
	 }

	QDomElement modelNode = contNode.namedItem("model").toElement();
	if ( !modelNode.isNull() ) {
		std::string modelName = EncoderBaseXmlQt::deserializeString( "type", "UNKNOWN", modelNode );
		wosh::building::BuildingGeometry::GEOMETRY_MODEL model = wosh::building::BuildingGeometry::getModelFromString(modelName.c_str());
		if ( model == wosh::building::BuildingGeometry::MODEL_UNKNOWN )
			ret = WRET_ERR_INTERNAL;
		else {
			wosh::building::Point3D pos; deserializePoint3D(pos, modelNode);
			double* values = new double[3];
			values[0] = pos.x;
			values[1] = pos.y;
			values[2] = pos.z;
			ret += object->buildGridFromModel(model, values, 3 );
			delete values;
		 }
	 }

	QDomElement bbNode = contNode.namedItem("bounding-box").toElement();
	if ( !bbNode.isNull() ) {
		wosh::building::Point3D bbox = object->getBoundingBox();
		deserializePoint3D(bbox, posNode);
		object->setBoundingBox(bbox);
	 }
	else
		ret += object->calculateBoundingBox();

	return ret;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

 WOSH_ENCODER_XML_Qt_BIND(wosh::persistence::qt::EncoderXml_Qt_Building_GardenZone, "wosh::building::GardenZone", 0.0, _static_EncoderXml_Qt_Building_GardenZone )

WRESULT EncoderXml_Qt_Building_GardenZone::serializeTo( const wosh::building::GardenZone* object, QDomDocument& doc, QDomElement& contNode, int encoder_options ) {
	if ( object == NULL ) return WRET_ERR_PARAM;
	WRESULT ret = EncoderXml_Qt_Building_BuildingObject::serializeTo(object, doc, contNode, encoder_options);
	EncoderBaseXmlQt::serializeBool( "enabled", object->isEnabled(), doc, contNode, encoder_options );
	EncoderBaseXmlQt::serializeLong( "priority", object->getPriority(), doc, contNode, encoder_options );
	QDomElement limitsNode = doc.createElement("limits"); contNode.appendChild(limitsNode);
	QDomElement timeNode = doc.createElement("time"); limitsNode.appendChild(timeNode);
	EncoderBaseXmlQt::serializeLong( "min", object->getLimitTimeMin(), doc, timeNode, encoder_options );
	EncoderBaseXmlQt::serializeLong( "max", object->getLimitTimeMax(), doc, timeNode, encoder_options );
	EncoderBaseXmlQt::serializeLong( "water-level", object->getLimitWaterLevel(), doc, limitsNode, encoder_options );
	EncoderBaseXmlQt::serializeLong( "period", object->getLimitTimePeriod(), doc, limitsNode, encoder_options );
	return ret;
 }

WRESULT EncoderXml_Qt_Building_GardenZone::deserializeFrom( wosh::building::GardenZone* object, const QDomElement& contNode ) {
	if ( object == NULL ) return WRET_ERR_PARAM;
	WRESULT ret = EncoderXml_Qt_Building_BuildingObject::deserializeFrom(object, contNode);
	object->setEnabled( EncoderBaseXmlQt::deserializeBool( "enabled", 0, contNode ) );
	object->setPriority( EncoderBaseXmlQt::deserializeLong( "priority", 0, contNode ) );
	QDomElement limitsNode = contNode.namedItem("limits").toElement();
	if ( !limitsNode.isNull() ) {
		object->setLimitTimeMin( EncoderBaseXmlQt::deserializeLong( "min", 0, limitsNode ) );
		object->setLimitTimeMax( EncoderBaseXmlQt::deserializeLong( "v", 0, limitsNode ) );
		object->setLimitWaterLevel( EncoderBaseXmlQt::deserializeLong( "water-level", 0, limitsNode ) );
		object->setLimitTimePeriod( EncoderBaseXmlQt::deserializeLong( "period", 0, limitsNode ) );
	 }
	return ret;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

  }; // namespace qt
 }; // namespace persistence
}; // namespace wosh
